﻿using System;
using System.ComponentModel;
using System.Text;

namespace DatabaseGroup.SSIS.SourceAdapters
{
    /// <summary>
    /// Class to convert between actual and readable column/row delimiters
    /// </summary>
    public class DelimiterStringConverter : StringConverter
    {
        private const string _none = "<none>";
        private static readonly string[] _readableDelimConsts = new[] { "{CR}", "{LF}", "Tab {t}", "Semicolon {;}", "Colon {:}", "Comma {,}", "Vertical Bar {|}" };
        private static readonly string[] _delimValueConsts = new[] { "\r", "\n", "\t", ";", ":", ",", "|" };

        /// <summary>
        /// Converts a string to its delimiter value, or
        /// calls the standard base method
        /// </summary>
        /// <param name="context">An ITypeDescriptorContext that provides format context</param>
        /// <param name="culture">The CultureInfo to use</param>
        /// <param name="value">The value to convert</param>
        /// <returns>The converted value</returns>
        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is string)
                return ToValueDelim((string)value);
          
            return base.ConvertFrom(context, culture, value);
        }

        /// <summary>
        /// Converts a string to its readable delimiter value, or
        /// calls the standard base method
        /// </summary>
        /// <param name="context">An ITypeDescriptorContext that provides format context</param>
        /// <param name="culture">The CultureInfo to use</param>
        /// <param name="value">The value to convert</param>
        /// <param name="destinationType">The Type to convert the parameter to</param>
        /// <returns>The converted value</returns>
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            if (value is string && destinationType == typeof(string))
                return ToReadableDelim((string)value);

            return base.ConvertTo(context, culture, value, destinationType);
        }

        /// <summary>
        /// Converts a delimiter value to its readable form
        /// </summary>
        /// <param name="delimValue">The delimiter value to convert</param>
        /// <returns>The readable string</returns>
        public static string ToReadableDelim(string delimValue)
        {
            if (string.IsNullOrEmpty(delimValue))
                return _none;
            
            StringBuilder sb = new StringBuilder(delimValue);
            for (int i = 0; i < _delimValueConsts.Length; i++)
            {
                sb = sb.Replace(_delimValueConsts[i], _readableDelimConsts[i]);
            }

            return sb.ToString();
        }

        /// <summary>
        /// Converts a readable delimiter to its value form
        /// </summary>
        /// <param name="delimValue">The readable delimiter value</param>
        /// <returns>The value form of the delimiter</returns>
        public static string ToValueDelim(string delimValue)
        {
            if (string.Compare(delimValue, _none) == 0)
                return string.Empty;
            
            StringBuilder sb = new StringBuilder(delimValue);
            for (int i = 0; i < _delimValueConsts.Length; i++)
            {
                sb = sb.Replace(_readableDelimConsts[i], _delimValueConsts[i]);
            }

            return sb.ToString();
        }
    }
}
